package com.fount4j.generator.introspector.extend;

import com.fount4j.generator.context.GeneratorContext;
import com.fount4j.generator.exception.GenerateException;
import com.fount4j.generator.info.ColumnInfo;
import com.fount4j.generator.info.DaoInfo;
import com.fount4j.generator.info.EntityInfo;
import com.fount4j.generator.info.JavaClassInfo;
import com.fount4j.generator.introspector.JavaClassIntrospector;
import com.fount4j.generator.util.BeanUtils;
import com.fount4j.generator.util.GeneratorFileUtils;
import com.fount4j.generator.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Dao 类解析器
 *
 * @author Morven 2016/12/22
 */
public class DaoIntrospector extends JavaClassIntrospector {
    /** Dao 类相对于实体类的名称后缀 */
    protected String nameSuffix = "Dao";

    /**
     * 解析 Dao 类
     *
     * @param context 生成器上下文
     */
    @Override
    public void introspect(GeneratorContext context) {
        DaoInfo info = new DaoInfo();
        introspectName(context, info);
        introspectPackage(context, info);
        introspectFile(context, info);
        introspectImports(context, info);
        introspectPrimaryKey(context, info);
        context.putInfo(infoKey, info);
    }

    /**
     * 解析主键相关的属性
     *
     * @param context 生成器上下文
     * @param info    DaoInfo
     */
    protected void introspectPrimaryKey(GeneratorContext context, DaoInfo info) {
        List<ColumnInfo> primaryKeyColumns = context.getTableInfo().getPrimaryKeyColumns();
        if (primaryKeyColumns.isEmpty()) {
            return;
        }
        if (primaryKeyColumns.size() > 1) {
            info.setPkJavaType(context.getInfo("entity").getName());
            info.setPkJavaTypeReference(((JavaClassInfo) context.getInfo("entity")).getReference());
        } else {
            ColumnInfo columnInfo = primaryKeyColumns.get(0);
            info.setPkJavaType(columnInfo.getJavaTypeName());
            info.setPkJavaTypeReference(columnInfo.getJavaType().getName());
        }
    }

    /**
     * 解析 Dao 类文件路径
     *
     * @param context 生成器上下文
     * @param info    DaoInfo
     */
    protected void introspectFile(GeneratorContext context, DaoInfo info) {
        String packageName = context.getTableConfig().getString("daoPackage");
        if (StringUtils.isBlank(packageName)) {
            packageName = this.packageName;
        }

        File file = GeneratorFileUtils.getFile(this.resourcePath, packageName, info.getName() + ".java");
        info.setFile(file);
        try {
            info.setCustomContent(GeneratorFileUtils.getCustomContent(file));
        } catch (IOException e) {
            throw new GenerateException("读取文件自定义内容出错: " + file, e);
        }
    }

    /**
     * 解析 Dao 类需要导入的包
     *
     * @param context 生成器上下文
     * @param info    DaoInfo
     */
    protected void introspectImports(GeneratorContext context, DaoInfo info) {
        Set<String> imports = new LinkedHashSet<>();
        File file = info.getFile();
        try {
            List<String> importList = GeneratorFileUtils.getImports(file);
            imports.addAll(importList);
        } catch (IOException e) {
            throw new GenerateException("读取类 import 内容出错: " + file, e);
        }

        EntityInfo entityInfo = context.getInfo("entity");
        if (!entityInfo.getPackageContent().equals(info.getPackageContent())) {
            imports.add(entityInfo.getReference());
        }

        if (this.imports != null) {
            imports.addAll(this.imports);
        }

        try {
            BeanUtils.removeUnuseImport(file, imports);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<String> importList = new ArrayList<>(imports);
        info.setImports(BeanUtils.createImportsList(importList));
    }

    /**
     * 解析 Dao 类的包路径
     *
     * @param context 生成器上下文
     * @param info    DaoInfo
     */
    protected void introspectPackage(GeneratorContext context, DaoInfo info) {
        String packageContent = context.getTableConfig().getString("daoPackage");
        if (StringUtils.isBlank(packageContent)) {
            packageContent = this.packageName;
        }

        String reference = info.getName();
        if (StringUtils.isBlank(packageContent)) {
            packageContent = "";
        } else {
            reference = packageContent + "." + reference;
            packageContent = "package " + packageContent + ";";
        }
        info.setPackageContent(packageContent);
        info.setReference(reference);
    }

    /**
     * 解析 Dao 类的名称
     *
     * @param context 生成器上下文
     * @param info    DaoInfo
     */
    private void introspectName(GeneratorContext context, DaoInfo info) {
        String daoName = context.getTableConfig().getString("daoName");
        if (StringUtils.isBlank(daoName)) {
            daoName = context.getInfo("entity").getName() + this.nameSuffix;
        }
        info.setName(daoName);
    }

    public String getNameSuffix() {
        return nameSuffix;
    }

    public void setNameSuffix(String nameSuffix) {
        this.nameSuffix = nameSuffix;
    }
}
